package com.gitee.feizns.quickstart.dict;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * {@link java.util.concurrent.ConcurrentMap}
 * @author feizns
 * @since 2024/12/12
 */
public class ConcurrentHashMapDictDepositor<T extends Entry> extends AbstractDictDepositor<T> {

    /**
     * 存储管理器
     */
    private final ConcurrentHashMap<String, T> entries = new ConcurrentHashMap<>();

    public ConcurrentHashMapDictDepositor() {
        this(new NothingToDoDictDepositor<>());
    }

    public ConcurrentHashMapDictDepositor(DictDepositor<T> delegate) {
        super(delegate);
    }

    @Override
    public DictDepositor<T> reload() {
        if ( delegate != null ) {
            delegate.reload();
            delegate.list().forEach(e -> this.entries.put(e.getKey(), e));
        }
        return this;
    }

    @Override
    public List<T> list() {
        return new ArrayList<>(entries.values());
    }

    @Override
    public T get(String key) {
        T entry = entries.get(key);
        //找不见下发查找
        if ( entry == null ) {
            //代理查找
            entry = delegate.get(key);
            //找见了存储到当前缓存
            if ( entry != null )
                entries.put(key, entry);
        }
        return entry;
    }

    @Override
    public void put(T entry) {
        T dict = get(entry.getKey());
        if ( dict != null && dict.getPermission() == Permission.ReadOnly )
            throw new UnsupportedOperationException(String.format("不支持修改只读字典[%s]", dict.getKey()));
        entries.put(entry.getKey(), entry);
        //代理存储
        delegate.put(entry);
    }

    @Override
    public boolean exists(String key) {
        return entries.containsKey(key);
    }

    @Override
    public T delete(String key) {
        T entry = get(key);
        if ( entry != null ) {
            if ( entry.getPermission() == Permission.ReadOnly )
                throw new UnsupportedOperationException(String.format("不支持删除只读字典[%s]", entry.getKey()));
            entries.remove(key);
            delegate.delete(key);
        }
        return entry;
    }

}
